home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac 1993 September / September 93.iso / Archives / Applications / Calculators / NumberCrunch 1.41 / Number Crunch II Demo / Library Routines / Text Examples / Fourier Transform < prev    next >
Encoding:
Text File  |  1992-09-03  |  6.6 KB  |  195 lines  |  [TEXT/NCII]

  1. ##########
  2. # Fourier Transforms
  3. #
  4. #   function FFT(Cx)  #  Returns the discrete fourier transform of Cx.
  5. #   function InvFFT(Ck) # Returns inverse discrete fourier transform.
  6. #
  7. #   function SwapSides(V)  # Returns array V with left and right halfs swapped.
  8. #
  9. #  With i=sqrt(-1), the transform is
  10. #
  11. #  Cx=InvFFT(Cq)    # (Sign= +1 transform) :
  12. #    Cx[q] =  Sum p=0…N-1 { exp( +i 2π p q/N ) Ck[p]  }
  13. #  Cq=FFT(Cx)         # (Sign= -1 transform) :
  14. #    Ck[p] =(1/N) Sum q=0…N-1 { exp( -i 2π p q/N ) Cx[q] }
  15. #  which has the normalization
  16. #   (1/N)  sum( |Cx|^2 ) = sum( |Ck|^2 ).
  17. #
  18. #  This text file explains and gives examples of
  19. #  some of the routines in the file All Library Routines, which
  20. #  should be Opened before trying any of these examples.
  21. #
  22. ##########
  23.  
  24.  
  25. #########
  26. # Here is the xCOD:
  27. xfft
  28.   # xCO2 xFFT(zN, Sign:real; cmplxData:ComplexArray; Error:real) , does a 1D Fast Fourier Transform on cmplxData[1..N]. zN must be a power of 2, else Error will be set to -1.; an external program.
  29.  
  30.  
  31. #################
  32. # Interface files:
  33. #
  34.  
  35.   function FFT(Cx)  #  Returns the discrete fourier transform of Cx.
  36. .   var n, Ck, err
  37. . #   Input:     Cx = real or complex array, 2^N points.
  38. . #   Output:   FFT = complex array = discrete fourier transform of Cx.
  39. .   begin
  40. .     Ck = Cx
  41. .     n = size(Ck)
  42. .     xFFT(n,-1,Ck,Err)
  43. .     if Err<>0 then
  44. .       begin 
  45. .         print(" •• ERROR in xFFT, err="+Err)
  46. .         FFT = 0/0  # which is "Not a number"
  47. .       end
  48. .     else
  49. .     FFT = Ck
  50. .   end
  51. .   
  52.  
  53.   function InvFFT(Ck) # Returns inverse discrete fourier transform.
  54. .   var n, Cx, err
  55. . #   Input:   Ck = real or complex 2^N array
  56. . #   Output:  InvFFT = inverse discrete fourier transform, a complex array.
  57. .   begin
  58. .     Cx = Ck
  59. .     n = size(Cx)
  60. .     xFFT(n,1,Cx,Err)
  61. .     if Err<>0 then
  62. .       begin 
  63. .         print(" •• ERROR in xFFT, err="+Err)
  64. .         invFFT = 0/0  # which is "Not a number"
  65. .       end
  66. .     else
  67. .     InvFFT = Cx
  68. .     end
  69. .     
  70.  
  71. #
  72. # The indeces are cyclic in the discrete fourier transform, with
  73. # Ck[N] the same as Ck[0]. FFT expects the "0 frequency" channel to 
  74. # be the first number in the Ck array, which means that 
  75. # the data is stored in the order
  76. #     Ck[0], Ck[1], Ck[2],... , Ck[N-1]. 
  77. # Because of the periodicity, Ck[N-1] is the same what would be 
  78. # Ck[-1]; therefore, if its often convenient to plot Ck and Cx in the
  79. # order Ck[N/2], Ck[N/2+1],... ,Ck[N-1], Ck[0], Ck[1],.. Ck[N/2 -1]
  80. # which puts 0 in the middle.  
  81.  
  82. # Here's a routine to swap the two sides of an array, so that
  83. # the x=0 or k=0 channel will be in the middle when we plot it.
  84.  
  85. # SwapSides(V) exchanges the left and right halves of a vector V.
  86. # Evaluate this by selecting it (or putting the cursor at the last
  87. # period) and hitting enter.
  88. #
  89.   function SwapSides(V)  # Returns array V with left and right halfs swapped.
  90. .    var n, n0, SS, left,right
  91. . # Input:   V[1…N]
  92. . # Output: SwapSides = { V[N/2], V[N/2+1], …, V[1],V[2,],…,V[N/2-1] }
  93. .   begin
  94. .     n = Size(V);  # the length of V
  95. .     n0 = FirstIndex(V); # V is V[n0...n0+n-1]
  96. .     SS = V  # save space for answer
  97. .     left = n0…(n0+n/2+1)  # left half indeces
  98. .     right = (n0+n/2)…(n0+n-1) # right half indeces
  99. .     SS[left] = V[right]
  100. .     SS[right] = V[left]
  101. .     SwapSides = SS    # return the answer
  102. .   end
  103. .   
  104.  
  105. ###########
  106. #  Example:
  107. #
  108.  
  109. N = 128;            # the number of points in the arrays.
  110. Cx[0…N-1] = 0;     # initialize the array.
  111. x = 0 … N-1;     # initialize the x co-ords of the array.
  112. xSwap = -N/2 … N/2-1;     # x co-ords of the "swapped" array.
  113.  
  114. # Here's a "hatbox" , with C=1 for |x|<=4.
  115. Cx[0] = 1;      
  116. Cx[1…4] = 1;
  117. Cx[N-4 … N-1] = 1;
  118. # To see this, plot [xSwap, SwapSides(Cx)]
  119.  
  120. # Finally, do the transform.
  121. Ck = FFT(Cx)           # <<<<<<<<<<<<   This does the actual transform.
  122.  
  123. # Several things went on there behind the scenes.
  124.  
  125. # First, Err didn't exist when xFFT was called, so it was created
  126. # as a single real number.
  127. Err
  128.   Err = 0 
  129.  
  130. # Second, Ck was a real array when passed to xFFT, but xFFT
  131. # expected a complex array. (See the argument list returned
  132. # when FFT was evaluated.)  So, Ck was converted to a complex
  133. # array (with 0's for the complex part), transformed, and returned.
  134. # Although you usually won't need to tell if an array is real or 
  135. # complex (and in fact NCII will at times convert it back and forth
  136. # like this if it needs to and the the imaginary part is zero), you can
  137. # tell how big an array really is by using Size and SizeAsIfReal, 
  138. # which aren't the same if the array or number is complex.
  139.  
  140. # If you really want to see when something's complex,
  141. # here's a function that will beep when it is..
  142. program BeepIfComplex(z)  # beeps if Z is complex.
  143. .   begin
  144. .      if Size(z) <> SizeAsIfReal(z) then beep
  145. .   end
  146. .   
  147.  
  148. # BeepIfComplex(Cx)   # This won't beep when evaluated without the "#".
  149. # BeepIfComplex(Ck)   #  This will.
  150.  
  151. # To see the transformed array, plot [xSwap, SwapSides(Ck)] .
  152. # This plots the real part of Ck. To see the imaginary part, you could
  153. # plot [xSwap, SwapSides(Imaginary(Ck))] ; 
  154. # but since Cx is symmetric, the imaginary part is zero
  155. # (except for numerical errors), so this is boring in this case.
  156. maximum(| Imaginary(Ck) |)
  157.    2.8649365e-16 
  158.  
  159. # Here is the check of the normalization:
  160. sum( |Ck|^2 )
  161.   0.0703125 
  162. 1/N sum( |Cx|^2 )
  163.   0.0703125 
  164.  
  165. # And finally, here's a table of some of the values. Note that these
  166. # have not been hit with SwapSides, so x=0 is the first number.
  167. # Table formats imaginary quantities as two colums of reals, 
  168. # so the last two columns are both Ck.  
  169. #
  170. # The actual table command is commented so that it won't do
  171. # anything if this whole file is evaluated. Just select it and hit
  172. # enter to make the table.
  173. #   j = 0…12; Table(j, Cx[j],Ck[j])
  174. #
  175. # x                 Cx                 Ck
  176. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
  177.    0                  1                  0.07031       0
  178.    1                  1                  0.06975       -5.455e-17
  179.    2                  1                  0.06807       -5.3077e-17
  180.    3                  1                  0.06534       -1.0133e-16
  181.    4                  1                  0.06161       -4.7384e-17
  182.    5                  0                  0.05701       -8.6654e-17
  183.    6                  0                  0.05165       -7.7217e-17
  184.    7                  0                  0.04568       -1.0006e-16
  185.    8                  0                  0.03928       -2.7712e-17
  186.    9                  0                  0.0326         -4.366e-17
  187.    10                0                  0.02583       -3.173e-17
  188.    11                0                  0.01913       -2.9912e-17
  189.    12                0                  0.01269       -8.5849e-18
  190.  
  191.  
  192.